#include "../../include/utils/sm4_utils.h" // 包含本模块的头文件，定义 SFTS_SM4_KEY 等
#include "../../include/sm2_params.h"      // 注意：这个头文件sm4_utils.c本身似乎没有用到，可以考虑移除
#include <gmssl/sm4.h>
#include <gmssl/rand.h>
#include <string.h>
#include <stdlib.h>

#define IV_LENGTH 16
#define BLOCK_SIZE 16

// 安全清除敏感数据
static void secure_zero(void *ptr, size_t size)
{
    volatile unsigned char *p = ptr;
    while (size--)
        *p++ = 0;
}

/**
 * @brief 生成SM4初始化向量 (原名 generate_iv)
 * @param iv 输出缓冲区（必须16字节）
 * @return 0成功 -1熵源不足
 * @details 使用GmSSL rand_bytes随机源
 */
int sfts_generate_iv(unsigned char *iv, size_t len) // 保持与头文件一致的函数名和参数
{
    if (len < 16)
        return -1; // IV 长度至少为16
    // 使用GmSSL rand_bytes接口
    return rand_bytes(iv, 16) == 1 ? 0 : -1;
}

/**
 * @brief 验证SM4加密数据的PKCS#7填充
 * @param buf 待验证的数据缓冲区（解密后的明文）
 * @param len 数据长度
 * @return 1-填充正确 0-填充错误
 * @details 检查最后一个字节的填充值，验证所有填充字节的一致性
 */
int verify_padding(const unsigned char *buf, int len)
{
    if (len <= 0)
        return 0; // 长度无效
    uint8_t pad = buf[len - 1];
    if (pad > 16 || pad < 1) // PKCS7填充值在1到16之间
        return 0;
    if (len < pad)
        return 0; // 数据长度小于填充长度，非法
    for (int i = 1; i <= pad; i++)
    {
        if (buf[len - i] != pad)
            return 0;
    }
    return 1;
}

// 使用GmSSL的SM4 API进行加密
int sfts_sm4_encrypt(const unsigned char *key, const unsigned char *iv,
                     const unsigned char *plaintext, int plaintext_len,
                     unsigned char *ciphertext)
{
    if (!key || !iv || !plaintext || !ciphertext || plaintext_len < 0)
        return -1;

    SM4_CBC_CTX cbc_ctx;
    size_t outlen = 0;
    size_t total_outlen = 0;
    int ret = -1;

    // 初始化CBC加密上下文 - 直接使用密钥数据
    if (sm4_cbc_encrypt_init(&cbc_ctx, key, iv) != 1)
    {
        return -1;
    }

    // 处理数据块
    if (sm4_cbc_encrypt_update(&cbc_ctx, plaintext, plaintext_len,
                               ciphertext, &outlen) != 1)
    {
        goto cleanup;
    }
    total_outlen = outlen;

    // 处理最后的填充
    size_t finish_outlen = 0;
    if (sm4_cbc_encrypt_finish(&cbc_ctx, ciphertext + outlen, &finish_outlen) != 1)
    {
        goto cleanup;
    }
    total_outlen += finish_outlen;
    ret = total_outlen;

cleanup:
    // 清除敏感数据
    secure_zero(&cbc_ctx, sizeof(SM4_CBC_CTX));
    return ret;
}

// 使用GmSSL的SM4 API进行解密
int sfts_sm4_decrypt(const unsigned char *key, const unsigned char *iv,
                     const unsigned char *ciphertext, int ciphertext_len,
                     unsigned char *plaintext)
{
    if (!key || !iv || !ciphertext || !plaintext || ciphertext_len < 0)
        return -1;

    // 密文长度必须是块大小的整数倍
    if (ciphertext_len % BLOCK_SIZE != 0)
    {
        return -1;
    }

    SM4_CBC_CTX cbc_ctx;
    size_t outlen = 0;
    size_t total_outlen = 0;
    int ret = -1;

    // 初始化CBC解密上下文 - 直接使用密钥数据
    if (sm4_cbc_decrypt_init(&cbc_ctx, key, iv) != 1)
    {
        return -1;
    }

    // 解密数据
    if (sm4_cbc_decrypt_update(&cbc_ctx, ciphertext, ciphertext_len,
                               plaintext, &outlen) != 1)
    {
        goto cleanup;
    }
    total_outlen = outlen;

    // 处理最后的填充
    size_t finish_outlen = 0;
    if (sm4_cbc_decrypt_finish(&cbc_ctx, plaintext + outlen, &finish_outlen) != 1)
    {
        goto cleanup;
    }
    total_outlen += finish_outlen;
    ret = total_outlen;

cleanup:
    // 清除敏感数据
    secure_zero(&cbc_ctx, sizeof(SM4_CBC_CTX));
    return ret;
}

// 兼容层函数实现 - 这些函数将逐步迁移到新API
void sfts_generate_sm4_key(SFTS_SM4_KEY *key)
{
    if (key)
    {
        rand_bytes(key->key, 16);
    }
}

void sfts_sm4_ecb_encrypt(const unsigned char *in, unsigned char *out, const SFTS_SM4_KEY *key)
{
    if (in && out && key)
    {
        SM4_KEY sm4_key;
        sm4_set_encrypt_key(&sm4_key, key->key);
        sm4_encrypt(&sm4_key, in, out);

        // 清除敏感数据
        secure_zero(&sm4_key, sizeof(SM4_KEY));
    }
}

void sfts_sm4_ecb_decrypt(const unsigned char *in, unsigned char *out, const SFTS_SM4_KEY *key)
{
    if (in && out && key)
    {
        SM4_KEY sm4_key;
        sm4_set_decrypt_key(&sm4_key, key->key);
        sm4_decrypt(&sm4_key, in, out);

        // 清除敏感数据
        secure_zero(&sm4_key, sizeof(SM4_KEY));
    }
}

/**
 * @brief 生成SM4-CBC模式初始化向量
 */
void sfts_sm4_cbc_encrypt(const unsigned char *in, unsigned char *out, size_t length,
                          const SFTS_SM4_KEY *key, const unsigned char *iv)
{
    if (in && out && key && iv && length % BLOCK_SIZE == 0)
    {
        // 使用新函数实现
        sfts_sm4_encrypt(key->key, iv, in, length, out);
    }
}

void sfts_sm4_cbc_decrypt(const unsigned char *in, unsigned char *out, size_t length,
                          const SFTS_SM4_KEY *key, const unsigned char *iv)
{
    if (in && out && key && iv && length % BLOCK_SIZE == 0)
    {
        // 使用新函数实现
        sfts_sm4_decrypt(key->key, iv, in, length, out);
    }
}